using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
using Pixysoft.SQL;

namespace Pixysoft
{
    public class SqlCoder
    {
        private static SqlCoder instance;

        public static SqlCoder Instance
        {
            get
            {
                lock (typeof(SqlCoder))
                {
                    if (instance == null)
                        instance = new SqlCoder();
                    return instance;
                }
            }
        }

        public SqlType GetSqlType(string sql)
        {
            sql = sql.ToUpper().Trim();

            if (sql.Contains("INSERT"))
                return SqlType.Insert;

            if (sql.Contains("UPDATE"))
                return SqlType.Update;

            if (sql.Contains("DELETE"))
            {
                return SqlType.Delete;
            }

            if (sql.Contains("SELECT"))
            {
                return SqlType.Select;
            }

            return SqlType.Unknown;
        }

        public string GetSqlTableName(string sql)
        {
            switch (GetSqlType(sql))
            {
                case SqlType.Select:
                    {
                        return GetSelectSqlTableName(sql);
                    }
                default:
                    break;
            }

            string reg1 = "(UPDATE [\\w\\d_]+)|(DELETE FROM [\\w\\d_]+)|(INSERT INTO [\\w\\d_]+)|(SELECT [,.\\w\\d_\\*]+ FROM [\\w\\d_]+)";

            string reg2 = "(UPDATE )|(DELETE FROM )|(INSERT INTO )|(SELECT [,.\\w\\d_\\*]+ FROM)";

            string midValue = Regex.Match(sql, reg1, RegexOptions.IgnoreCase).Value.Trim();

            return Regex.Replace(midValue, reg2, "", RegexOptions.IgnoreCase).Trim();
        }

        private string GetSelectSqlTableName(string sql)
        {
            SqlTokenizer tokener = new SqlTokenizer(sql);

            while (tokener.Next())
            {
                if ("FROM".Equals(tokener.GetToken(), StringComparison.OrdinalIgnoreCase))
                    break;
            }

            do { } while (tokener.Next() && tokener.TokenType != TokenType.NAME);

            return tokener.GetToken();
        }

        public List<string> GetParameters(string sql)
        {
            List<string> paraList = new List<string>();

            if (sql == null)
                return paraList;

            foreach (Match match in Regex.Matches(sql, ":[\\w]+"))
            {
                if (!paraList.Contains(match.Value.Replace(":", "")))
                {
                    paraList.Add(match.Value.Replace(":", ""));
                }
            }

            return paraList;

        }

        public bool HasParameter(string sql)
        {
            return GetParameters(sql).Count > 0;
        }

        public string GetSqlColumnName(DataTable table)
        {
            StringBuilder builder = new StringBuilder();

            foreach (DataColumn column in table.Columns)
            {
                builder.Append(string.Format("{0}.{1} AS {1}, ", table.TableName, column.ColumnName, column.ColumnName));
            }

            builder.Remove(builder.Length - 2, 2);

            return builder.ToString();
        }

        public string GetPureSqlColumnName(DataTable table)
        {
            StringBuilder builder = new StringBuilder();

            foreach (DataColumn column in table.Columns)
            {
                builder.Append(string.Format("{0}.{1}, ", table.TableName, column.ColumnName));
            }

            builder.Remove(builder.Length - 2, 2);

            return builder.ToString();
        }

        public SqlTable CreateSqlTable(string tablename, string columnname)
        {
            return new SqlTable(tablename, columnname);
        }
    }

    public enum SqlType
    {
        Insert,
        Update,
        Delete,
        Select,
        Unknown,
    }
}
